<?php

class debugComponent {

	public static $storage;
	public static $saveTo;
	public static $deBug;
	private static $logLevel = E_ALL;
	private static $wpdb;
	private static $table_error;
	private static $errorTypes =  array(
		E_PARSE => 'Parsing error',
		E_ALL => 'All Errors occured at once',
		E_WARNING => 'Warning',
		E_CORE_WARNING => 'Core warning',
		E_COMPILE_WARNING => 'Compile warning',
		E_USER_WARNING => 'User warning',
		E_ERROR => 'Error',
		E_CORE_ERROR => 'Core error',
		E_COMPILE_ERROR => 'Compile error',
		E_USER_ERROR => 'User error',
		E_RECOVERABLE_ERROR => 'Recoverable error',
		E_NOTICE => 'Notice',
		E_USER_NOTICE => 'User notice',
		E_STRICT => 'Strict error',
	);

	function __construct()
	{
		global $wpdb;
		self::$wpdb = $wpdb;
		self::$table_error = $wpdb->prefix."errors";
	}

	public static function init()
	{
		add_action("wp_head",array(__CLASS__,"getJSErrors"));
		add_action('wp_ajax_jsErrors',array(__CLASS__,'jsErrors'));
		add_action('wp_ajax_nopriv_jsErrors',array(__CLASS__,'jsErrors'));
		self::setDebug();
	}

	public static function jsErrors()
	{
		if(!empty($_POST['js_error']) && !empty($_POST['js_url']) && !empty($_POST['js_line'])){
			$js_error = explode(":",$_POST['js_error']);
			if(self::$storage == "db"){
				self::$wpdb->insert(self::$table_error,array(
					'types'=>'Javascript',
					'created'=>date('Y-m-d H:i:s'),
					'ip'=>self::get_client_ip(),
					'url'=>$_POST['js_url'],
					'error_types'=>$js_error[0],
					'error_messages'=>$js_error[0]." in ".$_POST['js_url'].' on line '.$_POST['js_line']
				));
			}else if(self::$storage == "files"){
				$lineError = "[Javascript] ";
				$lineError.= "[".self::get_client_ip()."]";
				$lineError.= " [".$_POST['js_url']."] ";
				$lineError.= "[".$js_error[0]."] ";
				$lineError.= $js_error[1]." in ".$_POST['js_url'].' on line '.$_POST['js_line']."\r\n";
				self::createLog($lineError);
			}
		}
		die();
	}

	public static function setDebug()
	{
		if(self::$deBug === "On" || self::$deBug === true){
			$mode = "On";
		}else if(self::$deBug === "Off" || self::$deBug === false){
			$mode = "Off";
		}
		ini_set('display_errors', $mode);
		ini_set('display_startup_errors', $mode);
		ini_set('html_errors', $mode);
	}

	public static function getFatalError()
	{
		$error = error_get_last();
		if(!empty($error['message'])){
			if(self::$storage == "db"){
				if(strpos($error['message'],"use mysqli or PDO instead")==false){
					self::$wpdb->insert(self::$table_error,array(
						'types'=>'PHP',
						'created'=>date('Y-m-d H:i:s'),
						'ip'=>self::get_client_ip(),
						'url'=>self::curPageURL(),
						'error_types'=>'Fatal error',
						'error_messages'=>$error['message']." in ".$error['file'].' on line '.$error['line']
					));
				}
			}else if(self::$storage == "files"){
				$lineError = "[PHP] ";
				$lineError.= "[".self::get_client_ip()."]";
				$lineError.= " [".self::curPageURL()."] ";
				$lineError.= "[Fatal error] ";
				$lineError.= $error['message']." in ".$error['file'].' on line '.$error['line']."\r\n";
				if(strpos($error['message'],"use mysqli or PDO instead")==false){
					self::createLog($lineError);
				}
			}
		}
	}

	public static function writeLog($error,$error_msg,$file_name,$line,$vars)
	{
		if(!($error && self::$logLevel && error_reporting())) {
			return;
		}
		if(!empty($error_msg)){
			if(self::$storage == "db"){
				self::$wpdb->insert(self::$table_error,array(
					'types'=>'PHP',
					'created'=>date('Y-m-d H:i:s'),
					'ip'=>self::get_client_ip(),
					'url'=>self::curPageURL(),
					'error_types'=>self::$errorTypes[$error],
					'error_messages'=>$error_msg." in ".$file_name.' on line '.$line
				));
			}else if(self::$storage == "files"){
				$lineError = "[PHP] ";
				$lineError.= "[".self::get_client_ip()."]";
				$lineError.= " [".self::curPageURL()."] ";
				$lineError.= "[".self::$errorTypes[$error]."] ";
				$lineError.= $error_msg." in ".$file_name.' on line '.$line."\r\n";
				self::createLog($lineError);
			}
		}
	}

	public static function createLog($content)
	{
	    if(!empty(self::$saveTo) && is_dir(self::$saveTo)) {
	        $path = self::$saveTo."/".date('d-m-Y').".log";
	        if(!file_exists($path)){
	            $file = fopen($path,'a');
	            fwrite($file, "[".date('d-M-Y H:i:s e')."] ".$content.PHP_EOL);
	        }else{
	            $file = fopen($path,'a+');
	            fwrite($file, "[".date('d-M-Y H:i:s e')."] ".$content.PHP_EOL);
	        }
	    }
	}

	public static function getJSErrors()
	{
		?>
		<script>
			window.onerror = function(error, url, line){
				var admin_url = "<?php echo admin_url('admin-ajax.php'); ?>";
				jQuery.post(admin_url,{
					action: "jsErrors",
					js_error: error,
					js_url: url,
					js_line: line
				},function(data){
					// TODO: something
				});
				<?php if(self::$deBug == "Off" || self::$deBug == false) : ?>
					return true;
				<?php endif; ?>
			};
		</script>
		<?php
	}

	public static function get_client_ip() {
        $ipaddress = '';
        if (getenv('HTTP_CLIENT_IP'))
            $ipaddress = getenv('HTTP_CLIENT_IP');
        else if(getenv('HTTP_X_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
        else if(getenv('HTTP_X_FORWARDED'))
            $ipaddress = getenv('HTTP_X_FORWARDED');
        else if(getenv('HTTP_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
        else if(getenv('HTTP_FORWARDED'))
            $ipaddress = getenv('HTTP_FORWARDED');
        else if(getenv('REMOTE_ADDR'))
            $ipaddress = getenv('REMOTE_ADDR');
        else
            $ipaddress = 'UNKNOWN';
        return $ipaddress;
    }

    public static function curPageURL() {
		$isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on");
		$port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443")));
		$port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : '';
		$url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.$_SERVER["REQUEST_URI"];
		return $url;
	}

	public static function clearLog($is_remove=false)
	{
		if($is_remove) {
			@unlink(date('d-m-Y').".log");
		}else{
			@file_put_contents(date('d-m-Y').".log", '');
		}
	}

}

set_error_handler(array('debugComponent','writeLog'));
register_shutdown_function(array('debugComponent','getFatalError'));